// 版权所有2011 Go作者。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

// 此文件设置universe作用域和不安全包。

package types2

import (
	"go/constant"
	"strings"
)

// 宇宙范围包含所有预先声明的Go对象。
// 它是任何嵌套作用域链的最外层作用域。
var Universe *Scope

// 不安全包装是进口商退回的包装
// 对于导入路径“不安全”。
var Unsafe *Package

var (
	universeIota  *Const
	universeByte  *Basic // uint8别名，但名称为“byte”
	universeRune  *Basic // int32别名，但名称为“符文”
	universeAny   *Interface
	universeError *Named
)

// Typ包含按其索引的预先声明的*基本类型
// 相应的BasicKind。
// None
// Typ[Byte]的*基本类型的名称为“uint8”。
// 使用Universe.Lookup（“byte”）.Type（）获取特定的
// 别名名为“byte”的基本类型（与“rune”类似）。
var Typ = [...]*Basic{
	Invalid: {Invalid, 0, "invalid type"},

	Bool:          {Bool, IsBoolean, "bool"},
	Int:           {Int, IsInteger, "int"},
	Int8:          {Int8, IsInteger, "int8"},
	Int16:         {Int16, IsInteger, "int16"},
	Int32:         {Int32, IsInteger, "int32"},
	Int64:         {Int64, IsInteger, "int64"},
	Uint:          {Uint, IsInteger | IsUnsigned, "uint"},
	Uint8:         {Uint8, IsInteger | IsUnsigned, "uint8"},
	Uint16:        {Uint16, IsInteger | IsUnsigned, "uint16"},
	Uint32:        {Uint32, IsInteger | IsUnsigned, "uint32"},
	Uint64:        {Uint64, IsInteger | IsUnsigned, "uint64"},
	Uintptr:       {Uintptr, IsInteger | IsUnsigned, "uintptr"},
	Float32:       {Float32, IsFloat, "float32"},
	Float64:       {Float64, IsFloat, "float64"},
	Complex64:     {Complex64, IsComplex, "complex64"},
	Complex128:    {Complex128, IsComplex, "complex128"},
	String:        {String, IsString, "string"},
	UnsafePointer: {UnsafePointer, 0, "Pointer"},

	UntypedBool:    {UntypedBool, IsBoolean | IsUntyped, "untyped bool"},
	UntypedInt:     {UntypedInt, IsInteger | IsUntyped, "untyped int"},
	UntypedRune:    {UntypedRune, IsInteger | IsUntyped, "untyped rune"},
	UntypedFloat:   {UntypedFloat, IsFloat | IsUntyped, "untyped float"},
	UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, "untyped complex"},
	UntypedString:  {UntypedString, IsString | IsUntyped, "untyped string"},
	UntypedNil:     {UntypedNil, IsUntyped, "untyped nil"},
}

var aliases = [...]*Basic{
	{Byte, IsInteger | IsUnsigned, "byte"},
	{Rune, IsInteger, "rune"},
}

func defPredeclaredTypes() {
	for _, t := range Typ {
		def(NewTypeName(nopos, nil, t.name, t))
	}
	for _, t := range aliases {
		def(NewTypeName(nopos, nil, t.name, t))
	}

	// 任何
	// （预先声明并进入宇宙范围，所以我们做所有
	// 普通支票；但后来又从范围中删除了，因为
	// 仅在类型参数列表中作为约束可见。）
	def(NewTypeName(nopos, nil, "any", &emptyInterface))

	// 错误的限定名称中有一个nil包，因为它不在任何包中
	{
		res := NewVar(nopos, nil, "", Typ[String])
		sig := &Signature{results: NewTuple(res)}
		err := NewFunc(nopos, nil, "Error", sig)
		typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()}
		sig.recv = NewVar(nopos, nil, "", typ)
		def(NewTypeName(nopos, nil, "error", typ))
	}
}

var predeclaredConsts = [...]struct {
	name string
	kind BasicKind
	val  constant.Value
}{
	{"true", UntypedBool, constant.MakeBool(true)},
	{"false", UntypedBool, constant.MakeBool(false)},
	{"iota", UntypedInt, constant.MakeInt64(0)},
}

func defPredeclaredConsts() {
	for _, c := range predeclaredConsts {
		def(NewConst(nopos, nil, c.name, Typ[c.kind], c.val))
	}
}

func defPredeclaredNil() {
	def(&Nil{object{name: "nil", typ: Typ[UntypedNil], color_: black}})
}

// 内置id是内置函数的id。
type builtinId int

const (
	// 宇宙范围
	_Append builtinId = iota
	_Cap
	_Close
	_Complex
	_Copy
	_Delete
	_Imag
	_Len
	_Make
	_New
	_Panic
	_Print
	_Println
	_Real
	_Recover

	// 包装不安全
	_Add
	_Alignof
	_Offsetof
	_Sizeof
	_Slice

	// 测试支持
	_Assert
	_Trace
)

var predeclaredFuncs = [...]struct {
	name     string
	nargs    int
	variadic bool
	kind     exprKind
}{
	_Append:  {"append", 1, true, expression},
	_Cap:     {"cap", 1, false, expression},
	_Close:   {"close", 1, false, statement},
	_Complex: {"complex", 2, false, expression},
	_Copy:    {"copy", 2, false, statement},
	_Delete:  {"delete", 2, false, statement},
	_Imag:    {"imag", 1, false, expression},
	_Len:     {"len", 1, false, expression},
	_Make:    {"make", 1, true, expression},
	_New:     {"new", 1, false, expression},
	_Panic:   {"panic", 1, false, statement},
	_Print:   {"print", 0, true, statement},
	_Println: {"println", 0, true, statement},
	_Real:    {"real", 1, false, expression},
	_Recover: {"recover", 0, false, statement},

	_Add:      {"Add", 2, false, expression},
	_Alignof:  {"Alignof", 1, false, expression},
	_Offsetof: {"Offsetof", 1, false, expression},
	_Sizeof:   {"Sizeof", 1, false, expression},
	_Slice:    {"Slice", 2, false, expression},

	_Assert: {"assert", 1, false, statement},
	_Trace:  {"trace", 0, true, statement},
}

func defPredeclaredFuncs() {
	for i := range predeclaredFuncs {
		id := builtinId(i)
		if id == _Assert || id == _Trace {
			continue // 仅在测试环境中定义这些
		}
		def(newBuiltin(id))
	}
}

// DefPredeclaredTestFuncs定义断言和跟踪内置项。
// 这些内置程序用于调试和测试此系统
// 只有包裹。
func DefPredeclaredTestFuncs() {
	if Universe.Lookup("assert") != nil {
		return // 已经定义
	}
	def(newBuiltin(_Assert))
	def(newBuiltin(_Trace))
}

func defPredeclaredComparable() {
	// “可比较”界面的定义如下
	// None
	// 类型可比接口{
	// ==（）非类型布尔
	// != （）非类型布尔
	// }
	// None
	// ==和！=无法由用户声明，但我们可以声明
	// magic方法==并在需要时检查其存在。

	// 定义接口{==（）}。我们不在乎签名
	// for==因此，将其留空，但接收器除外，它是
	// 稍后设置，以匹配通常的接口方法假设。
	sig := new(Signature)
	eql := NewFunc(nopos, nil, "==", sig)
	iface := NewInterfaceType([]*Func{eql}, nil).Complete()

	// 设置接口的定义类型
	obj := NewTypeName(nopos, nil, "comparable", nil)
	named := NewNamed(obj, iface, nil)
	obj.color_ = black
	sig.recv = NewVar(nopos, nil, "", named) // 完整==签名

	def(obj)
}

func init() {
	Universe = NewScope(nil, nopos, nopos, "universe")
	Unsafe = NewPackage("unsafe", "unsafe")
	Unsafe.complete = true

	defPredeclaredTypes()
	defPredeclaredConsts()
	defPredeclaredNil()
	defPredeclaredFuncs()
	defPredeclaredComparable()

	universeIota = Universe.Lookup("iota").(*Const)
	universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
	universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
	universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface)
	universeError = Universe.Lookup("error").(*TypeName).typ.(*Named)

	// “any”仅在类型参数列表中作为约束可见
	delete(Universe.elems, "any")
}

// 名称包含空格的对象是内部对象，不能输入到
// 范围。具有导出名称的对象将插入到不安全的包中
// 范围其他对象插入到宇宙范围中。
// None
func def(obj Object) {
	assert(obj.color() == black)
	name := obj.Name()
	if strings.Contains(name, " ") {
		return // 无事可做
	}
	// 修复命名类型的Obj链接
	if typ := asNamed(obj.Type()); typ != nil {
		typ.obj = obj.(*TypeName)
	}
	// 导出的标识符进入包不安全
	scope := Universe
	if obj.Exported() {
		scope = Unsafe.scope
		// 设置包装字段
		switch obj := obj.(type) {
		case *TypeName:
			obj.pkg = Unsafe
		case *Builtin:
			obj.pkg = Unsafe
		default:
			unreachable()
		}
	}
	if scope.Insert(obj) != nil {
		panic("internal error: double declaration")
	}
}
